<template>
  <view class="arco-rate">
    <view
      v-for="(item, index) in indexArray"
      :key="index"
      :style="style2(index)"
      :class="cls2(index)"
      @click="handleClick(index, true)"
      @animationend="handleAnimationEnd(index)"
    >
      <view :style="style(index)" class="arco-rate-character-right">
        <slot name="character" :index="index">
          <a-icon name="star"></a-icon>
        </slot>
      </view>
    </view>
  </view>
</template>

<script lang="ts">
import { useFormItem } from "@/ArcoUni/hook/use-form-item";
import { computed, defineComponent, ref, toRefs } from "vue";
import aIcon from "../arco-icon/index.vue";
import { isObject, isString } from "@/utils/is";
const Rate = defineComponent({
  name: "Rate",
  options: {
    // 虚拟化节点
    virtualHost: true,
  },
  components: {
    aIcon,
  },
  props: {
    count: {
      type: Number,
      default: 5,
    },
    modelValue: {
      type: Number,
      default: void 0,
    },
    defaultValue: {
      type: Number,
      default: 0,
    },
    allowHalf: {
      type: Boolean,
      default: false,
    },
    allowClear: {
      type: Boolean,
      default: false,
    },
    grading: {
      type: Boolean,
      default: false,
    },
    readonly: {
      type: Boolean,
      default: false,
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    color: {
      type: [String, Object],
      default: void 0,
    },
  },
  emits: ["update:modelValue", "change", "focus", "blur"],
  setup(props, { emit }) {
    const { disabled } = toRefs(props);
    const prefixCls = "arco-rate";
    const visible = ref(true);

    // eventHandlers
    const { mergedDisabled: _mergedDisabled, eventHandlers } = useFormItem({
      disabled,
    });

    const _value = ref(props.defaultValue);
    const animation = ref(false);
    const computedValue = computed(() => {
      var _a;
      return (_a = props.modelValue) != null ? _a : _value.value;
    });

    const displayIndex = computed(() => {
      return Math.round(computedValue.value);
    });

    const mergedDisabled = computed(
      () => _mergedDisabled.value || props.readonly,
    );

    const indexArray = computed(() => [
      ...Array(props.grading ? 5 : props.count),
    ]);

    const customColor = computed(() => {
      var _a;
      if (isString(props.color)) {
        return indexArray.value.map(() => props.color);
      }
      if (isObject(props.color)) {
        const sortedKeys = Object.keys(props.color)
          .map((key) => Number(key))
          .sort((a, b) => b - a);
        let threshold =
          (_a = sortedKeys.pop()) != null ? _a : indexArray.value.length;
        return indexArray.value.map((_, index2) => {
          var _a2;
          if (index2 + 1 > threshold) {
            threshold = (_a2 = sortedKeys.pop()) != null ? _a2 : threshold;
          }
          return props.color[String(threshold)];
        });
      }
      return void 0;
    });

    const handleClick = (index2, isHalf) => {
      if (mergedDisabled.value) {
        return;
      }
      var _a, _b, _c, _d;
      const newValue = isHalf && props.allowHalf ? index2 + 0.5 : index2 + 1;
      animation.value = true;
      if (newValue !== computedValue.value) {
        _value.value = newValue;
        emit("update:modelValue", newValue);
        emit("change", newValue);
        // eslint-disable-next-line @typescript-eslint/no-unused-expressions
        (_b = (_a = eventHandlers.value) == null ? void 0 : _a.onChange) == null
          ? void 0
          : _b.call(_a);
      } else if (props.allowClear) {
        _value.value = 0;
        emit("update:modelValue", 0);
        emit("change", 0);
        // eslint-disable-next-line @typescript-eslint/no-unused-expressions
        (_d = (_c = eventHandlers.value) == null ? void 0 : _c.onChange) == null
          ? void 0
          : _d.call(_c);
      }
    };

    const classNames = computed(() => {
      return [
        prefixCls,
        {
          [`${prefixCls}-readonly`]: props.readonly,
          [`${prefixCls}-disabled`]: _mergedDisabled.value,
        },
      ];
    });

    const cls2 = (index2) => {
      return [
        `${prefixCls}-character`,
        {
          [`${prefixCls}-character-half`]:
            props.allowHalf && index2 + 0.5 === displayIndex.value,
          [`${prefixCls}-character-full`]: index2 + 1 <= displayIndex.value,
          [`${prefixCls}-character-scale`]:
            animation.value && index2 + 1 < computedValue.value,
        },
      ];
    };

    const style = (index2) => {
      const style =
        customColor.value && index2 + 1 <= displayIndex.value
          ? {
              color: customColor.value[Math.ceil(displayIndex.value) - 1],
            }
          : void 0;
      return style;
    };

    const style2 = (index2) => {
      const style = animation.value
        ? {
            animationDelay: `${50 * index2}ms`,
          }
        : void 0;
      return style;
    };

    const handleAnimationEnd = (index2) => {
      if (animation.value && index2 + 1 >= computedValue.value - 1) {
        animation.value = false;
      }
    };

    return {
      prefixCls,
      classNames,
      visible,
      indexArray,
      style,
      cls2,
      style2,
      handleClick,
      handleAnimationEnd,
    };
  },
});
export default Rate;
</script>
